package com.lx.encryption.plugin.util;

import javassist.*;

import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;

/**
 * @author 刘志强
 * @title: AgentTransformer
 * @projectName class-encryption-plugin
 * @description: TODO
 * @date 2021/12/1911:27
 */
public class AgentTransformer implements ClassFileTransformer {

    /**
     * 加载配置文件的类
     */
    private static String classPathResource = "org/springframework/core/io/ClassPathResource";

    /**
     * spring asm 读取字节码的类
     */
    private static String classReader = "org/springframework/asm/ClassReader";

    /**
     * 密码
     */
    private String pwd;

    /**
     * 构造方法
     *
     * @param pwd 密码
     */
    public AgentTransformer(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain domain, byte[] classBuffer) {

        // 配置文件解读插装
        if (classPathResource.equals(className)) {
            CtClass ctClass;
            try {
                //使用全称,用于取得字节码类
                ClassPool classPool = ClassPool.getDefault();
                ctClass = classPool.makeClass(new ByteArrayInputStream(classBuffer));
                CtMethod mt = ctClass.getDeclaredMethod("getInputStream");
                String javaCode = "String c=" + "\"" + pwd + "\"" + ";" + "is=com.lx.encryption.plugin.util.JarDecryptor.getInstance().decryptConfigFile(this.path,is,c);";
                mt.insertAt(999, javaCode);
                return ctClass.toBytecode();
            } catch (Throwable e) {
                System.out.println("出错误了");
                e.printStackTrace();
            }
        }

        if (classReader.equals(className)) {
            try {
                System.out.println(className);
                ClassPool classPool = ClassPool.getDefault();
                classPool.appendClassPath(new LoaderClassPath(loader));
                CtClass ctClass = classPool.getCtClass("org.springframework.asm.ClassReader");
                CtClass ctClass1 = classPool.getCtClass("java.io.InputStream");
                CtConstructor ctConstructor = ctClass.getDeclaredConstructor(new CtClass[]{ctClass1});

                ctConstructor.setBody("this(com.lx.encryption.plugin.util.ClassUtils.readStream($1, false," + "\"" + pwd + "\"" + "));");
                return ctClass.toBytecode();
            } catch (Throwable e) {
                System.out.println("出错误了");
                e.printStackTrace();
            }
        }


        if (className == null || domain == null || loader == null) {
            return classBuffer;
        }

        //获取类所在的项目运行路径
        String projectPath = domain.getCodeSource().getLocation().getPath();
        projectPath = JarUtils.getRootPath(projectPath);
        if (StrUtils.isEmpty(projectPath)) {
            return classBuffer;
        }

        byte[] bytes = DESUtil.decryptByte(pwd, classBuffer);
        if (bytes != null) {
            System.out.println("解密类[" + className + "]");
            return bytes;
        }
        return classBuffer;

    }
}
